package com.ruoyi.web.service.impl;

import com.github.wxpay.sdk.WXPayConfig;
import com.github.wxpay.sdk.WXPayUtil;

import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.web.core.config.WamiConfig;
import com.ruoyi.web.core.config.WeChatURL;
import com.ruoyi.web.core.config.WechatConfig;
import com.ruoyi.web.core.config.YdcxConfig;
import com.ruoyi.web.entity.Result;
import com.ruoyi.web.entity.WxPay;
import com.ruoyi.web.entity.po.OrderPo;
import com.ruoyi.web.entity.po.WeChatUser;
import com.ruoyi.web.service.DepositService;
import com.ruoyi.web.utils.HttpClientManager;
import com.ruoyi.web.utils.HttpResult;
import com.ruoyi.web.utils.wechat.SnowflakeIdFactory;
import com.ruoyi.web.utils.wechat.WechatUtils;
import org.apache.http.NoHttpResponseException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 押金支付 DepositServiceImpl
 * @author zdh
 * @date 2020-07-03
 */
@Service("depositService")
public class DepositServiceImpl implements DepositService {
    private static Logger logger = LogManager.getFormatterLogger(DepositServiceImpl.class);

    @Resource
    private HttpClientManager httpClientManager;



    private String notifyUrl;

    /**
     * 获取支付参数 - 预支付押金模式现在支付押金
     * @param wxPay wxPay 支付参数信息
     * @param req req 获取支付微信的ip地址
     * @return Result
     */
    @Override
    public Result getPayInfo(WxPay wxPay, HttpServletRequest req) {

        //防止重复支付或者未授权支付（存在两套系统）





        //查询出是否绑定天蛙账号，若是代理或者商户扫99套餐设备则使用10元封顶套餐
//        WechatUtils.getWechatConfig("1607299523");

        //参数组装
        Map<String,String> payMap = new HashMap<>(10);
        payMap.put("appid", new YdcxConfig().getAppid());
        payMap.put("mch_id",new YdcxConfig().getMchId());
        payMap.put("nonce_str", WXPayUtil.generateNonceStr());
        payMap.put("openid",wxPay.getOpenid());
        payMap.put("body",new YdcxConfig().getBody());
        SnowflakeIdFactory snowflakeIdFactory = new SnowflakeIdFactory(5,1);
        payMap.put("out_trade_no",snowflakeIdFactory.nextId() + "");
        payMap.put("total_fee",1 + "");
        payMap.put("spbill_create_ip", WechatUtils.getIpAddr(req));
        payMap.put("notify_url","www.baidu.com");
        payMap.put("trade_type","JSAPI");
        //额外数据包   设备id，类型id，商户id，封顶消费时间（小时单位）
        payMap.put("attach",wxPay.getProductId() +",1607391587,17,"+new Date().getTime());
        return weChatUnifiedOrder(payMap,new YdcxConfig());
    }

    /**
     *  获取微信统一下单数据 - 连接微信统一下单数据
     * @param payMap payMap 支付参数
     * @return ReturnBase
     */
    private Result weChatUnifiedOrder(Map<String,String> payMap,YdcxConfig wechatConfig){
        String xml = WechatUtils.mapToXml(payMap, wechatConfig.getKey());
        if("fail".equals(xml)) { return Result.fail("支付单创建失败，请稍后再试"); }
        HttpResult httpResult = getWeChatUnifiedOrderInfo(xml, wechatConfig.getMchId(), 0);
        if(httpResult == null) { return Result.fail("系统繁忙，请稍后再试"); }
        if(httpResult.getStatusCode() == 200) {
            Map<String, String> map = WechatUtils.xmlToMap(httpResult.getContent());
            if(map == null) { return Result.fail("系统繁忙，请稍后再试"); }
            if("SUCCESS".equals(map.get("return_code"))) {
                payMap.put("prepay_id", map.get("prepay_id"));
                map.clear();
                map.put("package", "prepay_id=" + payMap.get("prepay_id"));
                map.put("signType", "MD5");
                map.put("appId", wechatConfig.getAppid());
                map.put("nonceStr", payMap.get("nonce_str"));
                map.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
                String paySign = WechatUtils.generateSignature(map,wechatConfig.getKey());
                if("fail".equals(paySign)) {
                    return Result.fail("系统繁忙，请稍后再试");
                }
                map.put("paySign", paySign);
                return Result.success("下单成功",map);
            }else {
                logger.info("【error】 微信统一下单失败：" + map.get("return_msg"));
                return Result.fail("系统繁忙，请稍后再试");
            }
        }else {
            logger.error("【error】：微信访问统一下单接口失败，失败原因：返回数据响应数据为null");
            return Result.fail("系统繁忙，请稍后再试");
        }
    }

    /**
     * 获取微信统一下单参数 ， 由于访问微信时容易出现 - api.mch.weixin.qq.com:443 failed to respond
     * NoHttpResponseException 当出现该异常为了提高用户体验讲再次发出请求
     * @param xml 支付参数
     * @param mchId 商户号
     * @return HttpResult
     */
    private HttpResult getWeChatUnifiedOrderInfo(String xml, String mchId, int payN){
        try {
            payN ++;
            return httpClientManager.doPostXml("https://" + WeChatURL.DOMAIN_API + WeChatURL.UNIFIEDORDER_URL_SUFFIX, xml ,mchId);
        } catch (NoHttpResponseException e) {
            logger.error("【error】 统一下单失败， 无返回对象信息。正在进行第 "+payN+" 次发起请求");
            if(payN < 2) {
                return getWeChatUnifiedOrderInfo(xml,mchId,payN);
            }
            return null;
        } catch (IOException e) {
            logger.error("【error】 统一下单失败，",e.getMessage(),e);
        }
        return null;
    }

    /**
     * 微信支付成功信息通知 , 读取请求对象中xml数据
     * @param req 请求对象
     * @param resp 响应对象
     */
    @Override
    public void wxDepositNotify(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        String content = WechatUtils.getReqStreamContent(req);
        if(!"fail".equals(content)) {
            Map<String, String> map = WechatUtils.xmlToMap(content);
            if(map != null) {
                if("SUCCESS".equals(map.get("return_code"))) {
                    if("SUCCESS".equals(map.get("result_code"))) {
                        weChatUserNotify(map);
                    }
                }
            }
        }
        resp.getWriter().write("<xml><return_code><![CDATA[SUCCESS]]></return_code>" +
                "<return_msg>![CDATA[OK]]</return_msg>" +
                "</xml>");
    }

    /**
     * 创建回调订单
     * @param map 回调数据
     * @return
     */
    @Override
    @Transactional(readOnly = false)
    public boolean weChatUserNotify(Map<String,String> map){
        Long orderNo = Long.parseLong(map.get("out_trade_no"));
        String transactionId = map.get("transaction_id");
        String openid = map.get("openid");
        String mchid = map.get("mch_id");
        String[] attach = map.get("attach").split(",");
        int productId = Integer.parseInt(attach[0]);
        int productType = Integer.parseInt(attach[1]);
        int siteId = Integer.parseInt(attach[2]);
        int menuTime = Integer.parseInt(attach[3]);
        int totalFee = Integer.parseInt(map.get("total_fee"));




        return true;
    }












}
